package db

import (
	"center/db/models"
	"common/uuid"
	"github.com/patrickmn/go-cache"
	"sync"
)

type nodeCache struct {
	mux        sync.RWMutex
	cache      *cache.Cache
	idxToIdMap map[uint32]uuid.UUID
}

func NewNodeCache(nodes []models.Node) *nodeCache {
	items := make(map[string]cache.Item)
	idxToIdMap := make(map[uint32]uuid.UUID)
	for _, node := range nodes {
		items[node.ID.String()] = cache.Item{
			Object:     &node,
			Expiration: 0,
		}
		idxToIdMap[node.IDx] = node.ID
	}
	return &nodeCache{
		cache:      cache.NewFrom(cache.NoExpiration, 0, items),
		idxToIdMap: idxToIdMap,
	}
}

func (n *nodeCache) Set(node models.Node) {
	n.cache.Set(node.ID.String(), &node, cache.NoExpiration)
	n.mux.Lock()
	n.idxToIdMap[node.IDx] = node.ID
	n.mux.Unlock()
}

func (n *nodeCache) GetById(nodeId uuid.UUID) (models.Node, bool) {
	if v, ok := n.cache.Get(nodeId.String()); ok {
		return *(v.(*models.Node)), true
	}
	return models.Node{}, false
}

func (n *nodeCache) GetByIdx(idx uint32) (models.Node, bool) {
	n.mux.RLock()
	nodeId, ok := n.idxToIdMap[idx]
	n.mux.RUnlock()
	if ok {
		return n.GetById(nodeId)
	}
	return models.Node{}, false
}

// NodeIdToIdx 通过id获取idx
func (n *nodeCache) NodeIdToIdx(nodeId uuid.UUID) uint32 {
	if v, ok := n.cache.Get(nodeId.String()); ok {
		return v.(models.Node).IDx
	}
	return 0
}

// NodeIdxToId 通过idx获取id
func (n *nodeCache) NodeIdxToId(idx uint32) uuid.UUID {
	n.mux.RLock()
	nodeId, _ := n.idxToIdMap[idx]
	n.mux.RUnlock()
	return nodeId
}
